#include "uart.h"
#pragma  diag_suppress 870

u8  STM2PC_Data_BUF[1024];	
u16 crc16_data = 0;
u8  Working_Mode = Normal_Mode;

//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 0
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 
}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式    
_sys_exit(int x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
	USART1->DR = (u8) ch;      
	return ch;
}
#endif


u16 crc16(u8 *addr, u16 num, u16 crc)
{
    u16 i;
	u16 x;
    for(x=0; x<num; x++)             
    {
        crc = crc ^ (addr[x] << 8);     /* Fetch byte from memory, XOR into CRC top byte*/
        for (i = 0; i < 8; i++)             /* Prepare to rotate 8 bits */
        {
            if (crc & 0x8000)            /* b15 is set... */
                crc = (crc << 1) ^ 0x1021;    /* rotate and XOR with polynomic */
            else                          /* b15 is clear... */
                crc <<= 1;                  /* just rotate */
        }                             /* Loop for 8 bits */
//        crc &= 0xFFFF;                  /* Ensure CRC remains 16-bit value */
    }                               /* Loop until num=0 */
    return(crc);                    /* Return updated CRC */
}


void USART1_config(void)
{
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enable GPIO clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
  
  /* Enable USART clock */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  
  /* Connect USART pins to AF7 */
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1);
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1);
  
  /* Configure USART Tx and Rx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
  GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* USARTx configuration ----------------------------------------------------*/
  /* USARTx configured as follow:
        - BaudRate = 3750000 baud
		   - Maximum BaudRate that can be achieved when using the Oversampling by 8
		     is: (USART APB Clock / 8) 
			 Example: 
			    - (USART1 APB1 Clock / 8) = (30 MHz / 8) = 3750000 baud
			    - (USART1 APB2 Clock / 8) = (60 MHz / 8) = 7500000 baud
		   - Maximum BaudRate that can be achieved when using the Oversampling by 16
		     is: (USART APB Clock / 16) 
			 Example: (USART1 APB1 Clock / 16) = (30 MHz / 16) = 1875000 baud
			 Example: (USART1 APB2 Clock / 16) = (60 MHz / 16) = 3750000 baud
        - Word Length = 8 Bits
        - one Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
  */
  USART_InitStructure.USART_BaudRate =115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART1, &USART_InitStructure);
  
  /* NVIC configuration */
  /* Configure the Priority Group to 2 bits */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* Enable the USARTx Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* Enable USART */
  USART_Cmd(USART1, ENABLE);
//	if(Working_Mode == Debug_Mode)
		USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
//	else
//		USART_ITConfig(USART1, USART_IT_RXNE, DISABLE);
}

void USART2_config(void)
{
  USART_InitTypeDef USART_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  GPIO_InitTypeDef GPIO_InitStructure;
  
  /* Enable GPIO clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
  
  /* Enable USART clock */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  
  /* Connect USART pins to AF7 */
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource5, GPIO_AF_USART2);
  GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_USART2);
  
  /* Configure USART Tx and Rx as alternate function push-pull */
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
  GPIO_Init(GPIOD, &GPIO_InitStructure);
  /* USARTx configuration ----------------------------------------------------*/
  /* USARTx configured as follow:
        - BaudRate = 3750000 baud
		   - Maximum BaudRate that can be achieved when using the Oversampling by 8
		     is: (USART APB Clock / 8) 
			 Example: 
			    - (USART1 APB1 Clock / 8) = (30 MHz / 8) = 3750000 baud
			    - (USART1 APB2 Clock / 8) = (60 MHz / 8) = 7500000 baud
		   - Maximum BaudRate that can be achieved when using the Oversampling by 16
		     is: (USART APB Clock / 16) 
			 Example: (USART1 APB1 Clock / 16) = (30 MHz / 16) = 1875000 baud
			 Example: (USART1 APB2 Clock / 16) = (60 MHz / 16) = 3750000 baud
        - Word Length = 8 Bits
        - one Stop Bit
        - No parity
        - Hardware flow control disabled (RTS and CTS signals)
        - Receive and transmit enabled
  */
  USART_InitStructure.USART_BaudRate =115200;
  USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  USART_InitStructure.USART_StopBits = USART_StopBits_1;
  USART_InitStructure.USART_Parity = USART_Parity_No;
  USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  USART_Init(USART2, &USART_InitStructure);
  
  /* NVIC configuration */
  /* Configure the Priority Group to 2 bits */
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
  
  /* Enable the USARTx Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
  /* Enable USART */
  USART_Cmd(USART2, ENABLE);
	if(Working_Mode == Debug_Mode)
		USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
	else
		USART_ITConfig(USART2, USART_IT_RXNE, DISABLE);
}


void stdout_putchar(u8 ch)
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART */
  USART_SendData(USART1, (uint8_t) ch);

  /* Loop until the end of transmission */
  while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
}

void stdout_putchar2(u8 ch)
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the USART */
  USART_SendData(USART2, (uint8_t) ch);

  /* Loop until the end of transmission */
  while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
}




void STM2PC_ERROR(USB_OTG_CORE_HANDLE *pdev,uint8_t  ep_addr,u8 State,u8 CMD,u8 ERROR_CODE,u8 Other_data)
{
//	u8 i=0;
	STM2PC_Data_BUF[0]=State;
    STM2PC_Data_BUF[1]=CMD;	   	
	STM2PC_Data_BUF[2]=0x15;			
	STM2PC_Data_BUF[3]=ERROR_CODE;  	
	STM2PC_Data_BUF[4]=Other_data;		
	STM2PC_Data_BUF[5]=0X00;	
	STM2PC_Data_BUF[6]=0X00;		
	STM2PC_Data_BUF[7]=0X00;	
	STM2PC_Data_BUF[8]=0X00;	
	STM2PC_Data_BUF[9]=0X00;	
	STM2PC_Data_BUF[10]=0X00;		
	STM2PC_Data_BUF[11]=0X00;		
	STM2PC_Data_BUF[12]=0X00;	  	
	STM2PC_Data_BUF[13]=0X00;		
	STM2PC_Data_BUF[14]=0X00;		
	STM2PC_Data_BUF[15]=0x00;
	STM2PC_Data_BUF[16]=0x00;
	STM2PC_Data_BUF[17]=0x00;
	STM2PC_Data_BUF[18]=0x00;
	STM2PC_Data_BUF[19]=0x00;
	STM2PC_Data_BUF[20]=0x00;
	STM2PC_Data_BUF[21]=0x00;
	STM2PC_Data_BUF[22]=0x00;
	crc16_data = crc16(STM2PC_Data_BUF, 23, 0xFFFF);	
	STM2PC_Data_BUF[23]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[24]=(u8)(crc16_data&0x00ff);

    DCD_EP_Tx(pdev,CDC_IN_EP,STM2PC_Data_BUF,25); 
    	
}

void STM2PC_RM671xx(USB_OTG_CORE_HANDLE *pdev,uint8_t  ep_addr, u8 table[],u8 length)
{
	u8 i=0;
    for(i=0;i<length;i++)
    {
        STM2PC_Data_BUF[i] = table[i];
    }
	crc16_data = crc16(STM2PC_Data_BUF, length, 0xFFFF);	
	STM2PC_Data_BUF[length]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[length+1]=(u8)(crc16_data&0x00ff);

    DCD_EP_Tx(pdev,CDC_IN_EP,STM2PC_Data_BUF,length+2); 
    	
}


void STM2PC_LCDConfig(USB_OTG_CORE_HANDLE *pdev,uint8_t  ep_addr,u8 CMD,u8 table[],u8 ERROR_CODE)
{
//	u8 i=0;
	STM2PC_Data_BUF[0]=0X0A;
    STM2PC_Data_BUF[1]=CMD;	   	
	STM2PC_Data_BUF[2]=0x15;	
	STM2PC_Data_BUF[3]=ERROR_CODE;	
	STM2PC_Data_BUF[4]=table[33];  	
	STM2PC_Data_BUF[5]=table[32];			//HP = 33<<8 + 32
	STM2PC_Data_BUF[6]=table[40];			//HF
	STM2PC_Data_BUF[7]=table[36];			//HB
	STM2PC_Data_BUF[8]=table[44];			//HS
	STM2PC_Data_BUF[9]=table[35];			
	STM2PC_Data_BUF[10]=table[34];			//VP = 35<<8 + 34
	STM2PC_Data_BUF[11]=table[42];			//VF
	STM2PC_Data_BUF[12]=table[38];			//VB
	STM2PC_Data_BUF[13]=table[46];	  	//VS
	STM2PC_Data_BUF[14]=table[50];			//50<<8 + 49  == 像素时钟  	
	STM2PC_Data_BUF[15]=table[49];		
	STM2PC_Data_BUF[16]=table[48];			//S_D_6_8 RGB/MIPI/DP
	STM2PC_Data_BUF[17]=table[56];			//LCDConfig
	STM2PC_Data_BUF[18]=table[63];			//RGB:0X55,MIPI:0XA1,0XA2,0XA3
	STM2PC_Data_BUF[19]=0x00;
	STM2PC_Data_BUF[20]=0x00;
	STM2PC_Data_BUF[21]=0x00;
	STM2PC_Data_BUF[22]=0x00;
	
	crc16_data = crc16(STM2PC_Data_BUF, 23, 0xFFFF);	
	STM2PC_Data_BUF[23]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[24]=(u8)(crc16_data&0x00ff);

    DCD_EP_Tx(pdev,CDC_IN_EP,STM2PC_Data_BUF,25); 	
}


void STM2PC_Pattern(USB_OTG_CORE_HANDLE *pdev,uint8_t  ep_addr,u8 CMD,u8 R,u8 G,u8 B,u8 ERROR_CODE)
{
//	u8 i=0;
	STM2PC_Data_BUF[0]=0X0A;
    STM2PC_Data_BUF[1]=CMD;	   	
	STM2PC_Data_BUF[2]=0x15;	
	STM2PC_Data_BUF[3]=ERROR_CODE;	
	STM2PC_Data_BUF[4]=R;  	
	STM2PC_Data_BUF[5]=G;	
	STM2PC_Data_BUF[6]=B;		
	STM2PC_Data_BUF[7]=0X00;	
	STM2PC_Data_BUF[8]=0X00;	
	STM2PC_Data_BUF[9]=0X00;	
	STM2PC_Data_BUF[10]=0X00;		
	STM2PC_Data_BUF[11]=0X00;		
	STM2PC_Data_BUF[12]=0X00;	  	
	STM2PC_Data_BUF[13]=0X00;		
	STM2PC_Data_BUF[14]=0X00;		
	STM2PC_Data_BUF[15]=0x00;
	STM2PC_Data_BUF[16]=0x00;
	STM2PC_Data_BUF[17]=0x00;
	STM2PC_Data_BUF[18]=0x00;
	STM2PC_Data_BUF[19]=0x00;
	STM2PC_Data_BUF[20]=0x00;
	STM2PC_Data_BUF[21]=0x00;
	STM2PC_Data_BUF[22]=0x00;
	
	crc16_data = crc16(STM2PC_Data_BUF, 23, 0xFFFF);	
	STM2PC_Data_BUF[23]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[24]=(u8)(crc16_data&0x00ff);

    DCD_EP_Tx(pdev,CDC_IN_EP,STM2PC_Data_BUF,25); 	
}


void STM2PC_SW_Version(USB_OTG_CORE_HANDLE *pdev,uint8_t  ep_addr,u8 State,u8 CMD,u8 ERROR_CODE,u8 Version,u8 SubVersion,u8 ID)
{
	STM2PC_Data_BUF[0]=State;
  STM2PC_Data_BUF[1]=CMD;	   	
	STM2PC_Data_BUF[2]=0x15;			
	STM2PC_Data_BUF[3]=ERROR_CODE;  	
	STM2PC_Data_BUF[4]=Version;		
	STM2PC_Data_BUF[5]=SubVersion;	
	STM2PC_Data_BUF[6]=ID;		
	STM2PC_Data_BUF[7]=0X00;	
	STM2PC_Data_BUF[8]=0X00;	
	STM2PC_Data_BUF[9]=0X00;	
	STM2PC_Data_BUF[10]=0X00;		
	STM2PC_Data_BUF[11]=0X00;		
	STM2PC_Data_BUF[12]=0X00;	  	
	STM2PC_Data_BUF[13]=0X00;		
	STM2PC_Data_BUF[14]=0X00;		
	STM2PC_Data_BUF[15]=0x00;
	STM2PC_Data_BUF[16]=0x00;
	STM2PC_Data_BUF[17]=0x00;
	STM2PC_Data_BUF[18]=0x00;
	STM2PC_Data_BUF[19]=0x00;
	STM2PC_Data_BUF[20]=0x00;
	STM2PC_Data_BUF[21]=0x00;
	STM2PC_Data_BUF[22]=0x00;
	crc16_data = crc16(STM2PC_Data_BUF, 23, 0xFFFF);	
	STM2PC_Data_BUF[23]=(u8)(crc16_data>>8);			
	STM2PC_Data_BUF[24]=(u8)(crc16_data&0x00ff);

    DCD_EP_Tx(pdev,CDC_IN_EP,STM2PC_Data_BUF,25);	
}

void STM2PC_FilConfig(USB_OTG_CORE_HANDLE *pdev,uint8_t  ep_addr,u8 State,u8 CMD,u8 table[],u16 num ,u8 ERROR_CODE)
{
		u16 i=0;
		STM2PC_Data_BUF[0]=State;
		STM2PC_Data_BUF[1]=CMD;	   	
		STM2PC_Data_BUF[2]=(u8)(num>>8);
		STM2PC_Data_BUF[3]=(u8)num;		
		STM2PC_Data_BUF[4]=ERROR_CODE;

		if(CMD == 0x01)
		{
				for(i=0;i<num;i++)
				STM2PC_Data_BUF[i+5]=table[i];  
		}		
		crc16_data = crc16(STM2PC_Data_BUF, num+5, 0xFFFF);	
		STM2PC_Data_BUF[num+5]=(u8)(crc16_data>>8);			
		STM2PC_Data_BUF[num+6]=(u8)(crc16_data&0x00ff);

		DCD_EP_Tx(pdev,CDC_IN_EP,STM2PC_Data_BUF,num+7);	
}

void Mode_Display(void)
{
	if(Working_Mode == Normal_Mode)
	{
			printf(" 当前工作模式为Normal_Mode\r\n");
			delay_ms(7);
		printf(" \r\n");
	}
			
	else
	{
			printf(" 当前工作模式为 Debug_Mode\r\n");
			delay_ms(7);
		printf(" \r\n");
	}
}



